<?php

/**
 * 安心站长axzz.cn，一个追求技术创造者。让网站、小程序、APP牛起来……
 *
 * cighsen02 365182575
 * 
 * Create at: 2024.05.06
 * Update at: 2025.09.03
 */

namespace Twoir\Service\ShowKey;

use Exception;
use InvalidArgumentException;

/**
 * 官方验证码
 */
class Image extends BaseImage implements OutputInterface
{
    /**
     * 验证码渲染
     *
     * @param array $add
     * @return string
     *
     * @throws Exception
     */
    public function render(array $add): string
    {
        return $this->base64DataURI($add, false);
    }

    /**
     * 生成图像
     *
     * @param array $add
     * @param bool $imageBase64
     * @return string
     * 
     * @throws Exception
     */
    public function base64DataURI(array $add, bool $imageBase64 = true): string
    {
        if (empty($add) || !isset($add['v']) || empty($add['v'])) throw new Exception('参数错误', 9200);

        if (!array_key_exists($add['v'], static::VERIFY_KEY)) throw new Exception('无效' . $add['v'], 9200);

        $question = strtolower($this->randomCharacters());

        if(is_bool($imageData = $this->imageData($question))) throw new Exception('生成失败', 9200);

        ecmsSetShowKey(static::VERIFY_KEY[$add['v']], $question);
        // 直出图象
        if (!$imageBase64) return $imageData;

        return sprintf('data:image/%s;base64,%s', $this->getContentType(), base64_encode($imageData));
    }

    /**
     * 生成图像
     *
     * @param string $value
     * @return string
     */
    protected function imageData(string $value): string
    {
        $image = imagecreate($this->width, $this->height);
        $bgcolor = imagecolorallocate($image, ...$this->bgcolor);
        $fontcolor = imagecolorallocate($image, ...$this->fontcolor);
        $distcolor = imagecolorallocate($image, ...$this->distcolor);
        $char_width = imagefontwidth($this->fontsize);
        $char_height = imagefontheight($this->fontsize);
        $calc = $this->imagettfbboxCalc([
            0 => 0,
            1 => 0,
            2 => $char_width * strlen($value),
            3 => 0,
            4 => $char_width * strlen($value),
            5 => $char_height,
            6 => 0,
            7 => $char_height
        ]);
        imagefill($image, 0, 0, $bgcolor);
        imagestring($image, $this->fontsize, $calc['x'], $calc['y'], $value, $fontcolor);

        // 加入干扰象素
        for($i = 0; $i < 90; $i++) {

            imagesetpixel($image, rand() % 70, rand() % 30, $distcolor);
        }

        ob_start();

        match ($this->imageType) {
            'png' => imagepng($image),
            'jpeg' => imagejpeg($image, null, 90),
            'gif' => imagegif($image),
            'wbmp' => imagewbmp($image),
            default => throw new InvalidArgumentException('不支持生成类型: ' . $this->imageType, 9200),
        };

        imagedestroy($image);

        return (string) ob_get_clean();
    }

    /**
     * 生成随机字符
     *
     * @param int $length
     * @return string
     */
    protected function randomCharacters(int $length = 4): string
    {
        // 字母
        if(1 === $this->keytog) {

            $low_ascii_bound	= 65;
            $upper_ascii_bound	= 90;
            $notuse				= [91];
        }
        // 数字+字母
        elseif(2 === $this->keytog) {

            $low_ascii_bound	= 50;
            $upper_ascii_bound	= 90;
            $notuse				= [58,59,60,61,62,63,64,73,79];
        }
        // 数字
        else {

            $low_ascii_bound	= 48;
            $upper_ascii_bound	= 57;
            $notuse				= [58];
        }

        $string = '';
        $i = 0;
        while($i < $length){

            mt_srand();
            $randnum = mt_rand($low_ascii_bound, $upper_ascii_bound);
            if(!in_array($randnum, $notuse)){

                $string .= chr($randnum);
                $i++;
            }
        }

        return $string;
    }
}
